package com.hengxinyongli.iam.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.hengxinyongli.iam.dto.Subject;
import com.hengxinyongli.iam.entity.Department;
import com.hengxinyongli.iam.entity.User;
import com.hengxinyongli.iam.entity.UserRole;
import com.hengxinyongli.iam.mapper.UserMapper;
import com.hengxinyongli.iam.mapper.UserRoleMapper;
import com.hengxinyongli.iam.utils.AssertUtils;
import com.hengxinyongli.iam.web.constant.Res;
import com.hengxinyongli.iam.web.controller.UserController;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author magic
 * @date 2018/9/26/026 13:55
 * @version 1.0
 * Description UserService
 */
@Service
public class UserService {

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserRoleMapper userRoleMapper;
    @Autowired
    DepartmentService departmentService;

    @Value("${pwd.sha.salt:!@#iam#@!}")
    private String shaSalt;

    public static void main(String[] args) {
        String pwd = DigestUtils.sha256Hex("123456" + "!@#iam#@!");
        System.out.println(pwd);
    }

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    public PageInfo<User> selectAllUsers(Integer pageNo, Integer pageSize, String userName, String status, String mobile) {
        if(Objects.isNull(pageNo)){
            pageNo = Integer.valueOf(1);
        }
        if(Objects.isNull(pageSize)){
            pageSize =  Integer.MAX_VALUE;
        }
        User user = new User();
        if (StringUtils.isNotBlank(userName)){
            user.setUserName(userName);
        }
        if(StringUtils.isNotBlank(status)){
            user.setStatus(status);
        }
        if(StringUtils.isNotBlank(mobile)){
            user.setMobile(mobile);
        }
        PageHelper.startPage(pageNo,pageSize);
        List<User> userList = userMapper.selectByModelSelective(user,false);
        Page<User> page = ((Page) userList);
        return  page.toPageInfo();
    }

    @Cacheable(value = "iamUser",key="T(String).valueOf(#id)")
    public User selectUserById(Long id) {
        return userMapper.selectByPrimaryKey(id);
    }

    public void usersCreate(User user, Set<String> userRoles) {
        User preUser = new User();
        preUser.setMobile(user.getMobile());
        List<User> users = userMapper.selectByModelSelective(preUser,true);
        AssertUtils.isTrue(users.isEmpty(), "用户手机号码已存在.");
        if(StringUtils.isNotBlank(user.getPassword())){
            String pwd = DigestUtils.sha256Hex(user.getPassword() + shaSalt);
            user.setPassword(pwd);
        }else {
            user.setPassword(null);
        }
        if(StringUtils.isNotBlank(user.getDepId())){
            Department department = departmentService.selectById(user.getDepId());
            AssertUtils.isTrue(Objects.nonNull(department),"指定部门信息不存在");
            user.setDepCode(department.getCode());
        }
        userMapper.insertSelective(user);
        userRoles.forEach(roleId -> {
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(user.getId());
            userRoleMapper.insertSelective(userRole);
        });
    }

    public Subject userLogin(String mobile, String password, Integer loginType,User loginUser) {
        Subject subject = new Subject();
        if(Objects.isNull(loginType)){
            String pwd = DigestUtils.sha256Hex(password + shaSalt);
            AssertUtils.isTrue(pwd.equals(loginUser.getPassword()),"登录失败，账号或密码错误!");
        }else{
            String smsCode = stringRedisTemplate.opsForValue().get(Res.SMS_LOGIN_PREFIX.concat(mobile));
            AssertUtils.isTrue(Objects.nonNull(smsCode),"登录前请先获取短信验证码!");
            AssertUtils.isTrue(smsCode.equals(password),"登录失败，账号或短信验证码错误!");
            stringRedisTemplate.delete(Res.SMS_LOGIN_PREFIX.concat(mobile));
        }
        subject.setUserId(loginUser.getId());
        subject.setUserName(loginUser.getUserName());
        subject.setMobile(loginUser.getMobile());
        subject.setUserType(loginUser.getUserType());
        subject.setDepId(loginUser.getDepId());
        subject.setDepLabel(loginUser.getDepCode());
        return subject;
    }

    private String[] getUserRoles(Long id) {
        UserRole userRole = new UserRole();
        userRole.setUserId(id);
        List<UserRole> userRoles = userRoleMapper.selectByModelSelective(userRole,true);
        Set<String> sets = Sets.newLinkedHashSet();
        userRoles.forEach( specUserRole ->{
            sets.add(specUserRole.getRoleId());
        });
        return Iterables.toArray(sets,String.class);
    }

    public User getLoginUser(String mobile) {
        User user = new User();
        user.setMobile(mobile);
        List<User> users = userMapper.selectByModelSelective(user,true);
        AssertUtils.isTrue(!users.isEmpty(),"用户信息不存在.");
        return users.get(0);
    }

    public User usersUpdate(Long id, UserController.UserRoUpdate userRo) {
        User currentUser = userMapper.selectByPrimaryKey(id);
        AssertUtils.isTrue(Objects.nonNull(currentUser),"指定用户不存在");
        User user = new User();
        BeanUtils.copyProperties(userRo,user);
        user.setId(id);
        if(StringUtils.isNotBlank(user.getPassword())){
            String pwd = DigestUtils.sha256Hex(user.getPassword() + shaSalt);
            user.setPassword(pwd);
        }else{
            user.setPassword(null);
        }
        if(StringUtils.isNotBlank(user.getDepId())){
            Department department = departmentService.selectById(user.getDepId());
            AssertUtils.isTrue(Objects.nonNull(department),"指定部门信息不存在");
            user.setDepCode(department.getCode());
        }
        userMapper.updateByPrimaryKeySelective(user);
        if(Objects.nonNull(userRo.getUserRoles()) && !userRo.getUserRoles().isEmpty()){
            UserRole deleteRole = new UserRole();
            deleteRole.setUserId(id);
            userRoleMapper.deleteByModelSelective(deleteRole,true);
            userRo.getUserRoles().forEach(role -> {
                UserRole userRole = new UserRole();
                userRole.setUserId(id);
                userRole.setRoleId(role);
                userRoleMapper.insertSelective(userRole);
            });
        }
        return userMapper.selectByPrimaryKey(id);
    }

    public void usersDelete(Long id) {
        User user = userMapper.selectByPrimaryKey(id);
        AssertUtils.isTrue(Objects.nonNull(user),"指定用户不存在");
        userMapper.deleteByPrimaryKey(id);
        UserRole userRole = new UserRole();
        userRole.setUserId(id);
        userRoleMapper.deleteByModelSelective(userRole,true);
    }

    public User userReset(Subject subject, String origin, String newer) {
        User user = userMapper.selectByPrimaryKey(subject.getUserId());
        AssertUtils.isTrue(Objects.nonNull(user),"指定用户不存在");
        String originPwd = DigestUtils.sha256Hex(origin + shaSalt);
        AssertUtils.isTrue(originPwd.equals(user.getPassword()),"修改失败，原密码输入错误！");
        User updUser = new User();
        updUser.setId(user.getId());
        updUser.setPassword(DigestUtils.sha256Hex(newer + shaSalt));
        userMapper.updateByPrimaryKeySelective(updUser);
        user = userMapper.selectByPrimaryKey(subject.getUserId());
        return user;
    }

    public List<User> fetchUserInfoByDepCode(String depCode) {
        User user = new User();
        user.setDepCode(depCode);
        List<User> users = userMapper.selectByModelSelective(user,true);
        return users;
    }
}
